<?php
/**
 * Created by PhpStorm.
 * User: Administrator
 * Date: 2017/11/20
 * Time: 13:19
 */
namespace App\Http\Controllers\Api;
use App\Helpers\Api\ApiResponse;
use App\Http\Controllers\Controller;
use App\Models\Addressee;
use App\Models\Machine;
use App\Models\MsgTaskLog;
use Carbon\Carbon;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Input;
use Symfony\Component\HttpFoundation\Response as FoundationResponse;
use Illuminate\Http\Request;
use Symfony\Component\HttpKernel\Exception\HttpException;
class MsgTaskController extends ApiController
{
    /**
     * @apiPermission none
     * @apiPermission anyone
     * @apiGroup MsgTask
     * @api {post} /api/v1/getMsgTask 获取消息任务
     * @apiName getMsgTask
     * @apiVersion 1.0.0
     * @apiDescription app 获取消息任务
     * @apiParam {String} machine 机器码
     * @apiParam {String} email 账号邮箱
     * @apiParam {String} serial 设备serial
     * @apiSuccess {json} Success-Response:
     * { "result": "测试" ,"status_code":0}
     * @apiSampleRequest /api/v1/getMsgTask
     */
    public function getMsgTask(Request $request)
    {
        try {
//            ini_set('default_socket_timeout', -1);
//            $this -> apiValidate($request , [
//                'machine' => "required",
//            ]);
                $machine = $request->get("machine");
                $redis = app("redis");
                $deviceKey = "msg:device:machine:" . $machine;
                // 查询今日完成任务数量
                $device_limit = $redis->get($deviceKey);
                $msg_task_device_limit = $redis->hget("config:msg_task_device_limit", "value");
                //获取设备活跃有效时间
                $deviceLiveExpire = $redis->hget("config:app_device_active_expire", "value");
                if ($deviceLiveExpire == 0) {
                    $deviceLiveExpire = 10;
                }
//                if ($device_limit >= $msg_task_device_limit) {
//                    return $this->error("该设备已完成今日任务");
//                }

                $fp = fopen("getmsg.txt", "w");
                if (!flock($fp, LOCK_EX)) {
                    return $this->error("系统繁忙，请稍后再试");
                }
                $msgTasksKeys = $redis->keys("dispatch:msgTask:*");
                if (!$msgTasksKeys) {
                    flock($fp, LOCK_UN);
                    return $this->error("任务为空");
                }
                $data = [];
                foreach ($msgTasksKeys as $msgTasksKey) {
                    $msgTask = $redis->hgetall($msgTasksKey);
                    //add 状态不是1 和不能用的过滤掉
                    if (isset($msgTask['status']) && $msgTask['status'] != 1) {
                        continue;
                    }
                    if (isset($msgTask['enable']) && $msgTask['enable'] != 1) {
                        continue;
                    }
                    if(empty($msgTask['file_column'])){
                        if ($msgTask['current_num'] >= $msgTask['target_num']) {
                            continue;
                        }
                    }
                    //当前此任务所用的设备数
//                    $current_limit = Machine::where("msg_task_id", $msgTask['id'])->count();
//                    if ($current_limit >= $msgTask['max_device_num']) {
//                        $is_run_task = Machine::where("msg_task_id", $msgTask['id'])->where("machine", $machine)->get();
//                        if ($is_run_task->isEmpty()) {
//                            continue;
//                        }
//                    }
                    if(!$msgTask['max_adress'] ||$msgTask['max_adress']==0 ){
                        $max_addressee = $redis->hget("config:max_addressee", "value");
                    }else{
                        $max_addressee = $msgTask['max_adress'];
                    }
                    //这里改变
                    if($msgTask['file_column']||!empty($msgTask['file_column'])){
                        $address_key ="msg:txt:". $msgTask['id'];
//                        if ($msgTask['current_num'] + $max_addressee >= $msgTask['target_num']) {
//                            $max_addressee = $msgTask['target_num'] - $msgTask['current_num'];
//                        }
                        $addressee = [];
                        $len = $redis -> llen($address_key);
                        if($len==0){
                            flock($fp, LOCK_UN);
                            return $this->error("收信人为空或任务已完成");
                        }
                        if($len <$max_addressee){
                            $max_addressee =$len;
                        }
                        for ($i =0 ; $i < $max_addressee ; $i ++)
                        {
                            $addressee[] = $redis -> lpop($address_key);
                        }
                        //if ($addressee) {
                        // $redis->srem($address_key , $addressee);
                        //}
                        if(count($addressee) == 0){
                            flock($fp, LOCK_UN);
                            return $this->error("收信人为空");
                        }
                    }else{

                        $address_key = "msg:app-enable-account:" . $msgTask['id'];
                        if ($msgTask['current_num'] + $max_addressee >= $msgTask['target_num']) {
                            $max_addressee = $msgTask['target_num'] - $msgTask['current_num'];
                        }
                        //从可用中取出需要个数
//                    $addressee = array_slice($redis->SMEMBERS($address_key), 0, $max_addressee);
//                    $diff_address = array_diff($redis->SMEMBERS($address_key), $addressee);
                        $addressee = [];
                        $len = $redis -> Scard($address_key);
                        if($len==0){
                            flock($fp, LOCK_UN);
                            return $this->error("收信人为空");
                        }
                        for ($i =0 ; $i < $max_addressee ; $i ++)
                        {
                            $addressee[] = $redis -> spop($address_key);
                        }
                        //if ($addressee) {
                        // $redis->srem($address_key , $addressee);
                        //}
                        if(count($addressee) == 0){
                            flock($fp, LOCK_UN);
                            return $this->error("收信人为空");
                        }
                    }
                    $data = [
                        'msg_task_id' => $msgTask['id'],
                        'msg_name' => $msgTask['name'],
                        'msg_content' => $msgTask['content'],
                        'msg_urls' => $msgTask['urls'],
                        'msg_link' => $msgTask['link'],
                        'ip' =>$msgTask['ip'],
                        'port'=>$msgTask['port'],
                        'num' => $max_addressee,
                        'addressee' => $addressee
                    ];
                    if ($data) {
                        //把机器和任务id绑定了
                        Machine::firstOrCreate([
                            'msg_task_id' => $msgTask['id'],
                            'machine' => $machine
                        ]);
                        break;
                    }
                }
                flock($fp, LOCK_UN);

                return $this->success($data);
        } catch (\Exception $e) {
            file_put_contents('aa.txt' , var_export($e ->getTraceAsString(), true),FILE_APPEND);
            return $this -> error($e ->getTrace());
        }
    }

    /**
     * @apiPermission none
     * @apiPermission anyone
     * @apiGroup MsgTask
     * @api {get} /api/v1/replyMsgTask 消息任务回执
     * @apiName replyMsgTask
     * @apiVersion 1.0.0
     * @apiDescription app 消息任务回执
     * @apiHeader {String} [Accept=application/json] Accept
     * @apiParam {String} machine 机器码
     * @apiParam {String} task_id 任务id
     * @apiParam {String} serial 设备serial
     * @apiParam {String} email 账号邮箱
     * @apiParam {String} addressee 收信人邮箱
     * @apiParam {String} status 0 成功 1 失败 2入列
     * @apiParam {String} log 日志
     * @apiSuccess {json} Success-Response:
     * { "result": "测试" ,"status_code":0}
     * @apiSampleRequest /api/v1/replyMsgTask
     */
    public function replyMsgTask(Request $request){
        $rep =$request ->getContent();
        if($rep){
            try {
                ini_set('default_socket_timeout', -1);
            $fp = fopen("replymsg1.txt", "w");
            if (!flock($fp, LOCK_EX)) {
                return $this->error("系统繁忙，请稍后再试");
            }
            $data =json_decode($request ->getContent());
            $task_id = $data->task_id;
            $machine = $data->machine;
            $serial = $data->serial;
            $email =$data->email;
            $task_key = "dispatch:msgTask:" . $task_id;
            $redis = app("redis");
            $deviceKey = "machine:device:" . $machine;
            $redis->incr($deviceKey);
            foreach($data->addressee as $key =>$value){
                foreach($value as $n =>$v){
//                    n  收件人 v状态
                    if($v ==2){
                        //如果列表假回到列表
                        $msgTask =$redis->hgetall("dispatch:msgTask:".$task_id);
                        if(empty($msgTask['file_column'])){
                            $address_key = "msg:app-enable-account:" . $task_id;
                            $redis ->sadd($address_key,$n);
                        }else{
                            $redis->rpush("msg:txt:".$task_id, $n);
                        }
                    }
                    if($v ==0 ){
                        $redis->HINCRBY($task_key, "current_num" , 1);
                    }
                    if($n){
                        DB::table("addressee")->where("number",$n)->increment('num');
                    }
                    $log = "msg:log:" .$task_id.":".$n.":".$v;
                    $logs['status']=$v;
                    $logs['msg_task_id']=$task_id;
                    $logs['deviced_sn']=$serial;
                    $logs['account_email']= $email;
                    $logs['msg_device_name']=$machine;
                    $logs['addressee']=$n;
                    $logs['current_at']=Carbon::now()->toDateTimeString();

                    $redis -> hmset($log , $logs);
//                    file_put_contents('DD.txt' , var_export($logs, true),FILE_APPEND);
                }
            }
            $deviceLiveExpire= $redis -> hget("config:app_device_active_expire" , "value");
            if($deviceLiveExpire== 0){
                $deviceLiveExpire =10;
            }
            //更新设备活跃记录
            $onlineDeviceLogKey ="app:online-device:" . $machine . ":" .$task_id;
            $redis ->hset($onlineDeviceLogKey,"machine",$machine);
            $redis ->hset($onlineDeviceLogKey,"task_id",$task_id);
            $redis->expire($onlineDeviceLogKey,$deviceLiveExpire*60);
            //更新设备状态
            $deviceDataKey = "app:device:" . $machine;
            $redis->hset($deviceDataKey,"name",$machine);
            $redis->hset($deviceDataKey,"status",1);
            $redis->hset($deviceDataKey,"last_active_time",time());
            //设备码和账号加1
            $account =$redis->keys("msg:account:*:".$email);
            if($account){
                $acc =$account[0];
                $redis->HINCRBY($acc, "num" , 1);
            }
            $code =$redis->keys("msg:device:*:*:".$serial);
            if($code){
                $co =$code[0];
                $redis->HINCRBY($co, "num" , 1);
            }
            flock($fp, LOCK_UN);
            return $this -> success("回调成功");
            } catch (\Exception $e) {
                return $this -> error($e -> getMessage());
            }
//            exit();
        }
        try {
            ini_set('default_socket_timeout', -1);
//            $this->apiValidate($request, [
//                "machine" => "required",
//                "serial" => "required",
//                "email" => "required",
//            ]);
            $fp = fopen("replymsg.txt", "w");
            if (!flock($fp, LOCK_EX)) {
                return $this->error("系统繁忙，请稍后再试");
            }
            $task_id = $request->get("task_id");
            $machine = $request->get("machine");
            $msg_device_version = $request->get("msg_device_version");
            $task_key = "dispatch:msgTask:" . $task_id;
            $redis = app("redis");
            if($request->get("status") ==2){
                $address_key = "msg:app-enable-account:" . $task_id;
                $redis ->sadd($address_key,$request->get("addressee"));

            }
            if($request->get("status") ==0 ){
                $redis->HINCRBY($task_key, "current_num" , 1);
            }
            $deviceKey = "machine:device:" . $machine;
            $redis->incr($deviceKey);
            if($request->get("addressee")){
                DB::table("addressee")->where("number",$request -> get("addressee"))->increment('num');
            }
            $log = "msg:log:" .$request->get("task_id").":".$request->get("addressee").":".$request->get("status");
            $logs['status']=$request->get("status");
            $logs['msg_task_id']=$task_id;
            $logs['deviced_sn']=$request->get("serial");
            $logs['account_email']= $request->get("email");
            $logs['msg_device_name']=$machine;
            $logs['msg_device_version']=$msg_device_version;
            $logs['addressee']=$request->get("addressee");
            $logs['current_at']=Carbon::now()->toDateTimeString();
            $redis -> hmset($log , $logs);
//            $redis = app("redis");
            $deviceLiveExpire= $redis -> hget("config:app_device_active_expire" , "value");
            if($deviceLiveExpire== 0){
                $deviceLiveExpire =10;
            }
            //更新设备活跃记录
            $onlineDeviceLogKey ="app:online-device:" . $machine . ":" .$task_id;
            $redis ->hset($onlineDeviceLogKey,"machine",$machine);
            $redis ->hset($onlineDeviceLogKey,"task_id",$task_id);
            $redis->expire($onlineDeviceLogKey,$deviceLiveExpire*60);
            //更新设备状态
            $deviceDataKey = "app:device:" . $machine;
            $redis->hset($deviceDataKey,"name",$machine);
            $redis->hset($deviceDataKey,"status",1);
            $redis->hset($deviceDataKey,"last_active_time",time());
            //设备码和账号加1
            $account =$redis->keys("msg:account:*:".$request->get("email"));
                if($account){
                    $acc =$account[0];
                    $redis->HINCRBY($acc, "num" , 1);
                }
            $code =$redis->keys("msg:device:*:*:".$request->get("serial"));
            if($code){
                $co =$code[0];
                $redis->HINCRBY($co, "num" , 1);
            }
            flock($fp, LOCK_UN);
            return $this -> success("回调成功");
        } catch (\Exception $e) {
            return $this -> error($e -> getMessage());
        }
    }
}
